home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 176-200 / 190 / nethack / twee.zoo / monmove.c < prev    next >
C/C++ Source or Header  |  1988-07-24  |  11KB  |  461 lines

  1. /*    SCCS Id: @(#)monmove.c  2.3     87/12/12
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  
  4. #include "hack.h"
  5. #include "mfndpos.h"
  6. #define NULL    (char *) 0
  7.  
  8. extern struct obj *mksobj_at();
  9. extern int warnlevel;    /* defined in mon.c */
  10.  
  11. dochugw(mtmp) register struct monst *mtmp; {
  12. register x = mtmp->mx;
  13. register y = mtmp->my;
  14. register d = dochug(mtmp);
  15. register dd;
  16.     if(!d)          /* monster still alive */
  17.     if(Warning)
  18.     if(!mtmp->mpeaceful)
  19.     if(mtmp->data->mlevel > warnlevel)
  20.     if((dd = dist(mtmp->mx,mtmp->my)) < dist(x,y))
  21.     if(dd < 100)
  22.     if(!canseemon(mtmp))
  23.         warnlevel = mtmp->data->mlevel;
  24.     return(d);
  25. }
  26.  
  27. /* returns 1 if monster died moving, 0 otherwise */
  28. dochug(mtmp)
  29. register struct monst *mtmp;
  30. {
  31.     register struct permonst *mdat;
  32.     register tmp, nearby, scared, onscary;
  33.  
  34.     if(mtmp->cham && !rn2(6))
  35.         (void) newcham(mtmp,
  36. #ifndef RPH
  37.                &mons[dlevel+14+rn2(CMNUM-14-dlevel)]);
  38. #else
  39.                (struct permonst *)0);
  40. #endif
  41.     mdat = mtmp->data;
  42.     if(mdat->mlevel < 0)
  43.         panic("bad monster %c (%d)",mdat->mlet,mdat->mlevel);
  44.  
  45.     /* regenerate monsters */
  46.     if((!(moves%20) || index(MREGEN, mdat->mlet)) &&
  47.         mtmp->mhp < mtmp->mhpmax)
  48.         mtmp->mhp++;
  49.  
  50.     if(mtmp->mfroz) {
  51.         if (Hallucination) pmon(mtmp);
  52.         return(0);      /* frozen monsters don't do anything */
  53.     }
  54.  
  55.     if(mtmp->msleep)        /* there is a chance we will wake it */
  56.         if(!disturb(mtmp)) return(0);
  57.  
  58.     /* not frozen or sleeping: wipe out texts written in the dust */
  59.     wipe_engr_at(mtmp->mx, mtmp->my, 1);
  60.  
  61.     /* confused monsters get unconfused with small probability */
  62.     if(mtmp->mconf && !rn2(50)) mtmp->mconf = 0;
  63.  
  64.     /* some monsters teleport */
  65.     if(mtmp->mflee && index("tNL", mdat->mlet) && !rn2(40)){
  66.         rloc(mtmp);
  67.         return(0);
  68.     }
  69.     if(mdat->mmove < rnd(6)) return(0);
  70.  
  71.     /* fleeing monsters might regain courage */
  72.     if(mtmp->mflee && !mtmp->mfleetim
  73.         && mtmp->mhp == mtmp->mhpmax && !rn2(25))
  74.         mtmp->mflee = 0;
  75.  
  76.     nearby = (dist(mtmp->mx, mtmp->my) < 3);
  77.     onscary = (sengr_at("Elbereth", u.ux, u.uy) ||
  78.             sobj_at(SCR_SCARE_MONSTER, u.ux, u.uy));
  79.     scared = (nearby && onscary && !mtmp->mtame && mtmp->mcansee)
  80.          && (mdat->mlet != '1');  /* RPH: the wiz is never scared */
  81.     if(scared && !mtmp->mflee) {
  82.         mtmp->mflee = 1;
  83.         mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100));
  84.     }
  85.  
  86.     if(!nearby ||
  87.         mtmp->mflee || scared ||
  88.         mtmp->mconf ||
  89.         (mtmp->minvis && !rn2(3)) ||
  90. #ifndef KOPS
  91.         (index("BIuy", mdat->mlet) && !rn2(4)) ||
  92. #else
  93.         (index("KBIuy", mdat->mlet) && !rn2(4)) ||
  94. #endif
  95.         (mdat->mlet == 'L' && !u.ugold && (mtmp->mgold || rn2(2))) ||
  96.         (!mtmp->mcansee && !rn2(4)) ||
  97.         mtmp->mpeaceful
  98.        ) {
  99.         tmp = m_move(mtmp,0);   /* 2: monster died moving */
  100.         if(tmp == 2 || (tmp && mdat->mmove <= 12))
  101.             return(tmp == 2);
  102.  
  103.         if(Hallucination && tmp==0) pmon(mtmp);
  104. /* If 0, this means the monster didn't move.  During hallucination, its
  105.    appearance should still change. */
  106.  
  107. #ifdef HARD
  108.         /* Without this line, fast monsters don't hit you when they've
  109.          * caught up to you. -dgk
  110.          */
  111.         nearby = (dist(mtmp->mx, mtmp->my) < 3);
  112.         scared = (nearby && onscary);
  113.         if(scared && !mtmp->mflee) {
  114.             mtmp->mflee = 1;
  115.             mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100));
  116.         }
  117. #endif
  118.     }
  119. #ifdef HARD    /* Demonic Blackmail!!! */
  120.     if(mdat->mlet == '&' && mtmp->mpeaceful
  121.        && !mtmp->mtame && !mtmp->isdjinni)
  122.         if(demon_talk(mtmp))
  123.              return(1);     /* you paid it off */
  124. #endif
  125.     if(!index("Ea", mdat->mlet) && nearby &&
  126.      !mtmp->mpeaceful && u.uhp > 0 && !scared) {
  127.         if(mhitu(mtmp))
  128.             return(1);      /* monster died (e.g. 'y' or 'F') */
  129.     }
  130.     /* extra movement for fast monsters */
  131.     if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp,1);
  132.     return(tmp == 2);
  133. }
  134.  
  135. m_move(mtmp,after)
  136. register struct monst *mtmp;
  137. {
  138. #ifndef REGBUG
  139.     register
  140. #endif
  141.          struct monst *mtmp2;
  142. #ifndef REGBUG
  143.     register
  144. #endif
  145.         int nx,ny,omx,omy,appr,nearer,cnt,i,j;
  146.     xchar gx,gy,nix,niy,chcnt;
  147.     schar chi;
  148.     boolean likegold, likegems, likeobjs;
  149. #ifdef KAA
  150.     boolean likerock;
  151. #endif
  152.     char msym = mtmp->data->mlet;
  153.     schar mmoved = 0;    /* not strictly nec.: chi >= 0 will do */
  154.     coord poss[9];
  155.     long info[9];
  156.  
  157.     if(mtmp->mfroz || mtmp->msleep)
  158.         return(0);
  159.     if(mtmp->mtrapped) {
  160.         i = mintrap(mtmp);
  161.         if(i == 2) return(2);   /* he died */
  162.         if(i == 1) return(0);   /* still in trap, so didnt move */
  163.     }
  164.     if(mtmp->mhide && o_at(mtmp->mx,mtmp->my) && rn2(10))
  165.         return(0);              /* do not leave hiding place */
  166.  
  167. #ifndef NOWORM
  168.     if(mtmp->wormno)
  169.         goto not_special;
  170. #endif
  171.  
  172.     /* my dog gets a special treatment */
  173.     if(mtmp->mtame) {
  174.         return( dog_move(mtmp, after) );
  175.     }
  176.  
  177.     /* likewise for shopkeeper */
  178.     if(mtmp->isshk) {
  179.         mmoved = shk_move(mtmp);
  180.         if(mmoved >= 0)
  181.             goto postmov;
  182.         mmoved = 0;        /* follow player outside shop */
  183.     }
  184.  
  185.     /* and for the guard */
  186.     if(mtmp->isgd) {
  187.         mmoved = gd_move();
  188.         goto postmov;
  189.     }
  190.  
  191. /* teleport if that lies in our nature ('t') or when badly wounded ('1') */
  192.     if((msym == 't' && !rn2(5))
  193.     || (msym == '1' && (mtmp->mhp < 7 || (!xdnstair && !rn2(5))
  194.         || RM_TYP(levl[u.ux][u.uy]) == STAIRS))) {
  195.         if(mtmp->mhp < 7 || (msym == 't' && rn2(2)))
  196.             rloc(mtmp);
  197.         else
  198.             mnexto(mtmp);
  199.         mmoved = 1;
  200.         goto postmov;
  201.     }
  202.  
  203.     /* spit fire ('D') or use a wand ('1') when appropriate */
  204. #ifdef DGKMOD
  205.     /* Add arrow and bolt throwing monsters */
  206.     if (index(
  207. # ifdef KAA
  208. #  ifdef KOPS
  209.         "D1OKC9",
  210. #  else
  211.         "D1KC9",
  212. #  endif
  213. # else
  214. #  ifdef KOPS
  215.         "D1OKC",
  216. #  else
  217.         "D1KC",
  218. #  endif
  219. # endif
  220.               msym))
  221.  
  222.         if (!inrange(mtmp))     /* inrange returns 1 if OK for mon */
  223.             return(0);      /* to move after it zaps or throws */
  224. #else
  225.     if(index("D1", msym))
  226.         inrange(mtmp);
  227. #endif
  228.  
  229.     if(msym == 'U' && !mtmp->mcan && canseemon(mtmp) &&
  230.         mtmp->mcansee && rn2(5)) {
  231.         if(!Confusion)
  232.             pline("%s's gaze has confused you!", Monnam(mtmp));
  233.         else
  234.             pline("You are getting more and more confused.");
  235.         if(rn2(3)) mtmp->mcan = 1;
  236.         HConfusion += d(3,4);           /* timeout */
  237.     }
  238. #ifdef RPH
  239.     if (msym == '8' && canseemon(mtmp)) {
  240.         if (mtmp->mcan)
  241.         pline ("You notice that %s isn't all that ugly.",monnam(mtmp));
  242.         else if (rn2(3))
  243.         pline ("You see the ugly back of %s.", monnam(mtmp));
  244.         else {
  245.         pline ("You look upon %s.", monnam(mtmp));
  246.         pline ("You turn to stone.");
  247.         done_in_by(mtmp);
  248.         }
  249.     }
  250. #endif
  251. not_special:
  252.     if(!mtmp->mflee && u.uswallow && u.ustuck != mtmp) return(1);
  253.     appr = 1;
  254.     if(mtmp->mflee) appr = -1;
  255.     if(mtmp->mconf || Invis ||  !mtmp->mcansee ||
  256.         (index("BIy", msym) && !rn2(3)))
  257.         appr = 0;
  258.     omx = mtmp->mx;
  259.     omy = mtmp->my;
  260.     gx = u.ux;
  261.     gy = u.uy;
  262.     if(msym == 'L' && appr == 1 && mtmp->mgold > u.ugold)
  263.         appr = -1;
  264.  
  265.     /* random criterion for 'smell' or track finding ability
  266.        should use mtmp->msmell or sth
  267.      */
  268.     if(msym == '@' ||
  269. #ifdef RPH
  270.       uwep && !strcmp(ONAME(uwep), "Excalibur") ||
  271. #endif
  272.       ('a' <= msym && msym <= 'z')) {
  273.     extern coord *gettrack();
  274.     register coord *cp;
  275.     schar mroom;
  276.         mroom = inroom(omx,omy);
  277.         if(mroom < 0 || mroom != inroom(u.ux,u.uy)){
  278.             cp = gettrack(omx,omy);
  279.             if(cp){
  280.             gx = cp->x;
  281.             gy = cp->y;
  282.             }
  283.         }
  284.     }
  285.  
  286.     /* look for gold or jewels nearby */
  287. #ifdef ROCKMOLE
  288.     likegold = (index("LODr", msym) != NULL);
  289.     likegems = (index("ODu", msym) != NULL);
  290. # ifdef KJSMODS
  291.     likeobjs = (mtmp->mhide || (msym == 'r' && dlevel > 3));
  292. # else
  293.     likeobjs = (mtmp->mhide || msym == 'r');
  294. # endif
  295. #else
  296.     likegold = (index("LOD", msym) != NULL);
  297.     likegems = (index("ODu", msym) != NULL);
  298.     likeobjs = mtmp->mhide;
  299. #endif
  300. #ifdef KAA
  301.     likerock = (msym == '9');
  302. #endif
  303. #define SRCHRADIUS    25
  304.     { xchar mind = SRCHRADIUS;        /* not too far away */
  305.       register int dd;
  306.       if(likegold){
  307.         register struct gold *gold;
  308.         for(gold = fgold; gold; gold = gold->ngold)
  309.           if((dd = DIST(omx,omy,gold->gx,gold->gy)) < mind){
  310.             mind = dd;
  311.             gx = gold->gx;
  312.             gy = gold->gy;
  313.         }
  314.       }
  315.       if(likegems || likeobjs
  316. #ifdef KAA
  317.                   || likerock
  318. #endif
  319.         )  {
  320.         register struct obj *otmp;
  321.         for(otmp = fobj; otmp; otmp = otmp->nobj)
  322.         if(likeobjs
  323.            || (likegems && otmp->olet == GEM_SYM)
  324. #ifdef KAA
  325.            || (likerock && otmp->olet == ROCK_SYM)
  326. #endif
  327.             )  {
  328.             if(msym != 'u' || objects[otmp->otyp].g_val != 0)
  329.                 if((dd = DIST(omx,omy,otmp->ox,otmp->oy)) < mind){
  330.                 mind = dd;
  331.                 gx = otmp->ox;
  332.                 gy = otmp->oy;
  333.                 }
  334.             }
  335.         }
  336.       if(mind < SRCHRADIUS && appr == -1) {
  337.         if(dist(omx,omy) < 10) {
  338.             gx = u.ux;
  339.             gy = u.uy;
  340.         } else
  341.             appr = 1;
  342.       }
  343.     }
  344.     nix = omx;
  345.     niy = omy;
  346.     cnt = mfndpos(mtmp,poss,info,
  347.         msym == 'u' ? NOTONL :
  348. #ifdef ROCKMOLE
  349. # ifdef KJSMODS
  350.         (msym == 'r' && dlevel > 3) ? ALLOW_WALL :
  351. # else
  352.         msym == 'r' ? ALLOW_WALL :
  353. # endif
  354. #endif
  355.         (msym == '@' || msym == '1') ? (ALLOW_SSM | ALLOW_TRAPS) :
  356.         index(UNDEAD, msym) ? NOGARLIC :
  357. #ifdef KAA
  358.             (msym == '9') ? (ALLOW_ROCK | ALLOW_TRAPS) : ALLOW_TRAPS);
  359. #else
  360.              ALLOW_TRAPS);
  361. #endif
  362.     chcnt = 0;
  363.     chi = -1;
  364.     for(i=0; i<cnt; i++) {
  365.         nx = poss[i].x;
  366.         ny = poss[i].y;
  367.         for(j=0; j<MTSZ && j<cnt-1; j++)
  368.             if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
  369.                 if(rn2(4*(cnt-j))) goto nxti;
  370. #ifdef STUPID
  371.         /* some stupid compilers think that this is too complicated */
  372.         { int d1 = DIST(nx,ny,gx,gy);
  373.           int d2 = DIST(nix,niy,gx,gy);
  374.           nearer = (d1 < d2);
  375.         }
  376. #else
  377.         nearer = (DIST(nx,ny,gx,gy) < DIST(nix,niy,gx,gy));
  378. #endif
  379.         if((appr == 1 && nearer) || (appr == -1 && !nearer) ||
  380.             !mmoved ||
  381.             (!appr && !rn2(++chcnt))){
  382.             nix = nx;
  383.             niy = ny;
  384.             chi = i;
  385.             mmoved = 1;
  386.         }
  387.     nxti:    ;
  388.     }
  389.     if(mmoved){
  390.         if(info[chi] & ALLOW_M){
  391.             mtmp2 = m_at(nix,niy);
  392.             if(hitmm(mtmp,mtmp2) == 1 && rn2(4) &&
  393.               hitmm(mtmp2,mtmp) == 2) return(2);
  394.             return(0);
  395.         }
  396.         if(info[chi] & ALLOW_U){
  397.           (void) hitu(mtmp, d(mtmp->data->damn, mtmp->data->damd)+1);
  398.           return(0);
  399.         }
  400.         mtmp->mx = nix;
  401.         mtmp->my = niy;
  402.         for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1];
  403.         mtmp->mtrack[0].x = omx;
  404.         mtmp->mtrack[0].y = omy;
  405. #ifndef NOWORM
  406.         if(mtmp->wormno) worm_move(mtmp);
  407. #endif
  408.     } else {
  409.         if(msym == 'u' && rn2(2)){
  410.             rloc(mtmp);
  411.             return(0);
  412.         }
  413. #ifndef NOWORM
  414.         if(mtmp->wormno) worm_nomove(mtmp);
  415. #endif
  416.     }
  417. postmov:
  418.     if(mmoved == 1) {
  419.         if(mintrap(mtmp) == 2)  /* he died */
  420.             return(2);
  421. #ifdef ROCKMOLE
  422.            /* Maybe a rock mole just ate something? */
  423.            if(msym == 'r'
  424. # ifdef KJSMODS
  425.           && dlevel > 3
  426. #endif
  427.           && IS_ROCK(RM_TYP(levl[mtmp->mx][mtmp->my])) &&
  428.           RM_TYP(levl[mtmp->mx][mtmp->my]) != POOL){
  429.            register int pile = rnd(25);
  430.            /* Just ate something. */
  431.            if (RM_TYP(levl[mtmp->mx][mtmp->my]) == 0)
  432.              RM_SET_TYP(levl[mtmp->mx][mtmp->my], CORR);
  433.            else if (IS_WALL(RM_TYP(levl[mtmp->mx][mtmp->my])))
  434.              RM_SET_TYP(levl[mtmp->mx][mtmp->my], DOOR);
  435.            mnewsym(mtmp->mx,mtmp->my);
  436.            /* Left behind a pile? */
  437.            if(pile < 5) {
  438.                if(pile == 1)
  439.             mksobj_at(ENORMOUS_ROCK, mtmp->mx, mtmp->my);
  440.               else
  441.             mksobj_at(ROCK, mtmp->mx, mtmp->my);
  442.            }
  443.           if(cansee(mtmp->mx, mtmp->my))
  444.             if(fobj)    atl(mtmp->mx,mtmp->my,fobj->olet);
  445.            }
  446.            /* Maybe a rock mole just ate some gold or armor? */
  447.            if(msym == 'r') meatgold(mtmp);
  448. #endif /* ROCKMOLE /**/
  449.         if(likegold) mpickgold(mtmp);
  450. #ifdef KAA
  451.         if(likerock || likegems) mpickgems(mtmp);
  452. #else
  453.         if(likegems) mpickgems(mtmp);
  454. #endif
  455.         if(mtmp->mhide) mtmp->mundetected = 1;
  456.     }
  457.     pmon(mtmp);
  458.     return(mmoved);
  459. }
  460.  
  461.